import datetime
from functools import wraps
import json

from django.core.paginator import Paginator
from django.db.models import Q, F, Count
from django.http import JsonResponse
from django.utils import timezone

# Create your views here.
from apps.activity.models import ActivityInfo, CommentInfo
from apps.user.models import UserInfo


# 更新活动状态装饰器
def refresh_status(func):
    @wraps(func)
    def fefresh(request):
        activity_obj = ActivityInfo.objects.exclude(
            Q(activity_status='0') | Q(activity_status='1') | Q(activity_status='5'))
        now_time = timezone.now()
        for activity_obj_item in activity_obj:
            if now_time > activity_obj_item.activity_create_time and now_time < activity_obj_item.activity_begin_time:
                activity_obj_item.activity_status = '2'
                activity_obj_item.save()
            elif now_time >= activity_obj_item.activity_begin_time and now_time < activity_obj_item.activity_end_time:
                activity_obj_item.activity_status = '3'
                activity_obj_item.save()
            else:
                activity_obj_item.activity_status = '4'
                activity_obj_item.save()

        for item in activity_obj:
            result = item.activity_comment_id.all().values('score').annotate(count=Count('score'))
            sum = 0
            num = 0
            for i in result:
                sum = sum + i['score'] * i['count']
                num = num + i['count']
            if sum != 0 and num != 0:
                item.activity_score = sum / num
                item.save()
        return func(request)

    return fefresh


# 检测请求方式装饰器
def check_method(func):
    @wraps(func)
    def is_post(request):
        if request.method != 'POST':
            result = {'code': 401, 'error': '请求方式错误！'}
            return JsonResponse(result, json_dumps_params={"ensure_ascii": False}, )
        else:
            # 取出请求的body体并把json格式转为python字典形式
            json_obj = json.loads(request.body)
            return func(request, json_obj)

    return is_post


# 创建活动
def create_activity_view(request):
    if request.method != 'POST':
        result = {'code': 401, 'error': '请求方式错误！'}
        return JsonResponse(result, json_dumps_params={"ensure_ascii": False}, )
    else:
        try:
            file = request.FILES['activityCover']
            json_obj = json.loads(request.POST['data'])
            user_name = json_obj['userName']
            activity_name = json_obj['activityName']
            activity_people_max_num = json_obj['activityPeopleMaxNum']
            activity_province = json_obj['activityProvince']
            activity_city = json_obj['activityCity']
            activity_district = json_obj['activityDistrict']
            activity_address = json_obj['activityAddress']
            activity_begin_time = datetime.datetime.strptime(json_obj['activityBeginTime'], '%Y-%m-%d %H:%M:%S')
            activity_end_time = datetime.datetime.strptime(json_obj['activityEndTime'], '%Y-%m-%d %H:%M:%S')
            activity_tag = json_obj['activityTag']
            activity_detail = json_obj['activityDetail']
        except Exception as e:
            print(e)
            result = {'code': 402, 'error': '未获取到数据或数据变量名错误！'}
            return JsonResponse(result, json_dumps_params={"ensure_ascii": False}, )

        try:
            user_obj = UserInfo.objects.get(user_name=user_name)
            if not user_obj.is_management:
                result = {'code': 403, 'error': '用户权限不够！'}
                return JsonResponse(result, json_dumps_params={"ensure_ascii": False}, )
            else:
                file.name = f'{timezone.now()} + {user_obj.phone}.jpg'
                activity_obj = ActivityInfo(activity_name=activity_name, activity_initiator=user_obj)
                activity_obj.activity_participator_num = 1
                activity_obj.activity_initiator_phone = user_obj.phone
                activity_obj.activity_people_max_num = activity_people_max_num
                activity_obj.activity_province = activity_province
                activity_obj.activity_city = activity_city
                activity_obj.activity_district = activity_district
                activity_obj.activity_address = activity_address
                activity_obj.activity_begin_time = activity_begin_time
                activity_obj.activity_end_time = activity_end_time
                activity_obj.activity_tag = activity_tag
                activity_obj.activity_detail = activity_detail
                activity_obj.activity_cover = file
                activity_obj.save()
                activity_obj.joined_id.add(user_obj)
                activity_obj.save()

                result = {'code': 200, 'success': '创建活动成功！'}
                return JsonResponse(result, json_dumps_params={"ensure_ascii": False}, )
        except Exception as e:
            print(e)
            result = {'code': 403, 'error': '用户不存在！'}
            return JsonResponse(result, json_dumps_params={"ensure_ascii": False}, )


# 进入首页推荐最新发布的3条活动
def index_recommend_view(request):
    activity_obj = ActivityInfo.objects.exclude(
        Q(activity_status='0') | Q(activity_status='1') | Q(activity_status='5')).order_by(
        '-activity_create_time').values()
    list_activity_obj = list(activity_obj)
    data = []

    if len(list_activity_obj) == 0:
        result = {'code': 403, 'error': '暂无活动！'}
        return JsonResponse(result, json_dumps_params={"ensure_ascii": False}, )
    elif len(list_activity_obj) < 3:
        for i in list_activity_obj:
            data.append(i)
    else:
        for i in range(0, 3):
            data.append(list_activity_obj[i])

    result = {'code': 200, 'data': data}
    return JsonResponse(result, json_dumps_params={"ensure_ascii": False}, )


# 活动页请求对应页码的活动信息 改动
@refresh_status
@check_method
def activity_page_view(request, json_obj):
    try:
        choice_activity_status = json_obj['choice_activity_status']
        page = json_obj['page']

        # 默认情况
        if choice_activity_status == 0:
            activity_obj = ActivityInfo.objects.exclude(
                Q(activity_status='0') | Q(activity_status='1') | Q(activity_status='5')).order_by(
                '-activity_participator_num').values()
        # 报名中
        elif choice_activity_status == 1:
            activity_obj = ActivityInfo.objects.filter(activity_status='2').order_by(
                '-activity_participator_num').values()
        # 活动中
        elif choice_activity_status == 2:
            activity_obj = ActivityInfo.objects.filter(activity_status='3').order_by(
                '-activity_participator_num').values()
        # 已结束
        else:
            activity_obj = ActivityInfo.objects.filter(activity_status='4').order_by(
                '-activity_participator_num').values()

        if len(activity_obj) == 0:
            result = {'code': 403, 'error': '活动为空！'}
            return JsonResponse(result, json_dumps_params={"ensure_ascii": False}, )
        elif len(activity_obj) < 3:
            paginator = Paginator(activity_obj, len(activity_obj))
        else:
            paginator = Paginator(activity_obj, 3)

        page_num = paginator.num_pages
        page_obj = paginator.page(page)
        return JsonResponse({'code': 200, 'data': list(page_obj.object_list), 'pageNum': page_num})
    except Exception as e:
        print(e)
        result = {'code': 402, 'error': '未获取到数据或数据变量名错误！'}
        return JsonResponse(result, json_dumps_params={"ensure_ascii": False}, )


# 活动详情 改动
@check_method
def activity_detail_view(request, json_obj):
    try:
        activity_id = json_obj['id']

        activity_obj_dict = ActivityInfo.objects.filter(id=activity_id).values()
        activity_obj = list(ActivityInfo.objects.filter(id=activity_id))

        collected_user_objs = list(activity_obj[0].collect_id.all().values())
        joined_user_objs = list(activity_obj[0].joined_id.all().values())
        comments_objs = list(activity_obj[0].activity_comment_id.all().values())
        result = {'code': 200, 'data': list(activity_obj_dict), 'joiner': joined_user_objs,
                  'collecter': collected_user_objs, 'comments': comments_objs}
        return JsonResponse(result, json_dumps_params={"ensure_ascii": False}, )
    except Exception as e:
        print(e)
        result = {'code': 402, 'error': '未获取到数据或数据变量名错误！'}
        return JsonResponse(result, json_dumps_params={"ensure_ascii": False}, )


# 参加活动
@check_method
def join_activity_view(request, json_obj):
    try:
        activity_id = json_obj['id']
        user_name = json_obj['userName']
        try:
            activity_obj = ActivityInfo.objects.get(id=activity_id)
            user_obj = UserInfo.objects.get(user_name=user_name)

            is_joined = len(activity_obj.joined_id.filter(id=user_obj.id).values())

            if activity_obj.activity_people_max_num == activity_obj.activity_participator_num:
                return JsonResponse({'code': 403, 'error': '活动报名已满！'})

            if not is_joined:
                activity_obj.joined_id.add(user_obj)
                activity_obj.activity_participator_num = F('activity_participator_num') + 1
                activity_obj.save()

                result = {'code': 200, 'success': '参加成功！'}
                return JsonResponse(result, json_dumps_params={"ensure_ascii": False}, )
            else:
                result = {'code': 403, 'error': '已参加过！'}
                return JsonResponse(result, json_dumps_params={"ensure_ascii": False}, )
        except Exception as e:
            print(e)
            result = {'code': 403, 'error': '用户或活动不存在！'}
            return JsonResponse(result, json_dumps_params={"ensure_ascii": False}, )

    except Exception as e:
        print(e)
        result = {'code': 402, 'error': '未获取到数据或数据变量名错误！'}
        return JsonResponse(result, json_dumps_params={"ensure_ascii": False}, )


# 查看自己参加的活动
@refresh_status
@check_method
def self_join_activity_view(request, json_obj):
    try:
        user_name = json_obj['userName']
        try:
            user_obj = UserInfo.objects.get(user_name=user_name)

            self_activity_obj = user_obj.activities.exclude(activity_status='5').values()

            result = {'code': 200, 'data': list(self_activity_obj)}
            return JsonResponse(result, json_dumps_params={"ensure_ascii": False}, )
        except Exception as e:
            print(e)
            result = {'code': 403, 'error': '用户不存在！'}
            return JsonResponse(result, json_dumps_params={"ensure_ascii": False}, )
    except Exception as e:
        print(e)
        result = {'code': 402, 'error': '未获取到数据或数据变量名错误！'}
        return JsonResponse(result, json_dumps_params={"ensure_ascii": False}, )


# 查看自己发起的活动
@refresh_status
@check_method
def self_create_activity_view(request, json_obj):
    try:
        user_name = json_obj['userName']
        try:
            user_obj = UserInfo.objects.get(user_name=user_name)

            self_activity_obj = user_obj.initiator_id.exclude(activity_status='5').values()

            result = {'code': 200, 'data': list(self_activity_obj)}
            return JsonResponse(result, json_dumps_params={"ensure_ascii": False}, )
        except Exception as e:
            print(e)
            result = {'code': 403, 'error': '用户不存在！'}
            return JsonResponse(result, json_dumps_params={"ensure_ascii": False}, )
    except Exception as e:
        print(e)
        result = {'code': 402, 'error': '未获取到数据或数据变量名错误！'}
        return JsonResponse(result, json_dumps_params={"ensure_ascii": False}, )


# 收藏活动 改动
@check_method
def collect_activity_view(request, json_obj):
    try:
        activity_id = json_obj['id']
        user_name = json_obj['userName']
        try:
            activity_obj = ActivityInfo.objects.get(id=activity_id)
            user_obj = UserInfo.objects.get(user_name=user_name)

            is_collected = len(activity_obj.collect_id.filter(id=user_obj.id).values())

            if not is_collected:
                activity_obj.collect_id.add(user_obj)
                activity_obj.activity_collected_num = F('activity_collected_num') + 1
                activity_obj.save()

                result = {'code': 200, 'success': '收藏成功！'}
                return JsonResponse(result, json_dumps_params={"ensure_ascii": False}, )
            else:
                result = {'code': 403, 'error': '已收藏过！'}
                return JsonResponse(result, json_dumps_params={"ensure_ascii": False}, )
        except Exception as e:
            print(e)
            result = {'code': 403, 'error': '用户或活动不存在！'}
            return JsonResponse(result, json_dumps_params={"ensure_ascii": False}, )

    except Exception as e:
        print(e)
        result = {'code': 402, 'error': '未获取到数据或数据变量名错误！'}
        return JsonResponse(result, json_dumps_params={"ensure_ascii": False}, )


# 查看自己收藏的活动
@refresh_status
@check_method
def self_collect_activity_view(request, json_obj):
    try:
        user_name = json_obj['userName']
        try:
            user_obj = UserInfo.objects.get(user_name=user_name)

            self_collect_activity_obj = user_obj.collect_activities.exclude(activity_status='5').values()

            result = {'code': 200, 'data': list(self_collect_activity_obj)}
            return JsonResponse(result, json_dumps_params={"ensure_ascii": False}, )
        except Exception as e:
            print(e)
            result = {'code': 403, 'error': '用户不存在！'}
            return JsonResponse(result, json_dumps_params={"ensure_ascii": False}, )
    except Exception as e:
        print(e)
        result = {'code': 402, 'error': '未获取到数据或数据变量名错误！'}
        return JsonResponse(result, json_dumps_params={"ensure_ascii": False}, )


# 取消收藏
@check_method
def cancle_collect_activity_view(request, json_obj):
    try:
        activity_id = json_obj['id']
        user_name = json_obj['userName']
    except Exception as e:
        print(e)
        result = {'code': 402, 'error': '未获取到数据或数据变量名错误！'}
        return JsonResponse(result, json_dumps_params={"ensure_ascii": False}, )

    try:
        activity_obj = ActivityInfo.objects.get(id=activity_id)
        user_obj = UserInfo.objects.get(user_name=user_name)

        is_collected = len(activity_obj.collect_id.filter(id=user_obj.id).values())

        if is_collected:
            activity_obj.collect_id.remove(user_obj)
            activity_obj.activity_collected_num = F('activity_collected_num') - 1
            activity_obj.save()

            result = {'code': 200, 'success': '取消收藏成功！'}
            return JsonResponse(result, json_dumps_params={"ensure_ascii": False}, )
        else:
            result = {'code': 403, 'error': '还未收藏！'}
            return JsonResponse(result, json_dumps_params={"ensure_ascii": False}, )
    except Exception as e:
        print(e)
        result = {'code': 403, 'error': '用户或活动不存在！'}
        return JsonResponse(result, json_dumps_params={"ensure_ascii": False}, )


# 退出活动
@check_method
def exit_activity_view(request, json_obj):
    try:
        activity_id = json_obj['id']
        user_name = json_obj['userName']
    except Exception as e:
        print(e)
        result = {'code': 402, 'error': '未获取到数据或数据变量名错误！'}
        return JsonResponse(result, json_dumps_params={"ensure_ascii": False}, )

    try:
        activity_obj = ActivityInfo.objects.get(id=activity_id)
        user_obj = UserInfo.objects.get(user_name=user_name)

        is_joined = len(activity_obj.joined_id.filter(id=user_obj.id).values())

        if is_joined:
            activity_obj.joined_id.remove(user_obj)
            activity_obj.activity_participator_num = F('activity_participator_num') - 1
            activity_obj.save()

            result = {'code': 200, 'success': '退出成功！'}
            return JsonResponse(result, json_dumps_params={"ensure_ascii": False}, )
        else:
            result = {'code': 403, 'error': '还未参加！'}
            return JsonResponse(result, json_dumps_params={"ensure_ascii": False}, )
    except Exception as e:
        print(e)
        result = {'code': 403, 'error': '用户或活动不存在！'}
        return JsonResponse(result, json_dumps_params={"ensure_ascii": False}, )


# 删除活动
@check_method
def del_activity_view(request, json_obj):
    try:
        activity_id = json_obj['id']
    except Exception as e:
        print(e)
        result = {'code': 402, 'error': '未获取到数据或数据变量名错误！'}
        return JsonResponse(result, json_dumps_params={"ensure_ascii": False}, )

    ActivityInfo.objects.filter(id=activity_id).update(activity_status='5')

    result = {'code': 200}
    return JsonResponse(result, json_dumps_params={"ensure_ascii": False}, )


# 搜索活动
@check_method
def search_activity(request, json_obj):
    try:
        search_text = json_obj['search_text']
    except Exception as e:
        print(e)
        result = {'code': 402, 'error': '未获取到数据或数据变量名错误！'}
        return JsonResponse(result, json_dumps_params={"ensure_ascii": False}, )

    activity_objs = ActivityInfo.objects.filter(activity_name__contains=search_text).exclude(
        Q(activity_status='0') | Q(activity_status='1') | Q(activity_status='5')).values()

    result = {'code': 200, 'data': list(activity_objs)}
    return JsonResponse(result, json_dumps_params={"ensure_ascii": False}, )


# 城市过滤器
@check_method
def city_search_activity(request, json_obj):
    try:
        search_rules = json_obj['search_rules']
        page = json_obj['page']
    except Exception as e:
        print(e)
        result = {'code': 402, 'error': '未获取到数据或数据变量名错误！'}
        return JsonResponse(result, json_dumps_params={"ensure_ascii": False}, )

    length = len(search_rules)

    if length == 1:
        activity_objs = list(ActivityInfo.objects.filter(activity_province=search_rules[0]).exclude(
            Q(activity_status='0') | Q(activity_status='1') | Q(activity_status='5')).values())
    elif length == 2:
        activity_objs = list(
            ActivityInfo.objects.filter(
                Q(activity_province=search_rules[0]) & Q(activity_city=search_rules[1])).exclude(
                Q(activity_status='0') | Q(activity_status='1') | Q(activity_status='5')).values())
    elif length == 3:
        activity_objs = list(ActivityInfo.objects.filter(
            Q(activity_province=search_rules[0]) & Q(activity_city=search_rules[1]) & Q(
                activity_district=search_rules[2])).exclude(
            Q(activity_status='0') | Q(activity_status='1') | Q(activity_status='5')).values())
    else:
        activity_objs = list(ActivityInfo.objects.filter(
            Q(activity_province=search_rules[0]) & Q(activity_city=search_rules[1]) & Q(
                activity_district=search_rules[2]) & Q(activity_district=search_rules[3])).exclude(
            Q(activity_status='0') | Q(activity_status='1') | Q(activity_status='5')).values())

    if len(activity_objs) == 0:
        result = {'code': 403, 'error': '活动为空！'}
        return JsonResponse(result, json_dumps_params={"ensure_ascii": False}, )
    elif len(activity_objs) < 3:
        paginator = Paginator(activity_objs, len(activity_objs))
    else:
        paginator = Paginator(activity_objs, 3)

    page_num = paginator.num_pages
    page_obj = paginator.page(page)
    return JsonResponse({'code': 200, 'data': list(page_obj.object_list), 'pageNum': page_num})


# 发表评论
@check_method
def send_comment(request, json_obj):
    try:
        is_child = json_obj['isChild']
        user_name = json_obj['userName']
        comment_text = json_obj['comment_text']
    except Exception as e:
        print(e)
        result = {'code': 402, 'error': '未获取到数据或数据变量名错误！'}
        return JsonResponse(result, json_dumps_params={"ensure_ascii": False}, )

    try:
        if not is_child:
            activity_id = json_obj['id']
            score = json_obj['score']
            activity_obj = ActivityInfo.objects.get(id=activity_id)
            user_obj = UserInfo.objects.get(user_name=user_name)

            comment_obj = CommentInfo(comment_text=comment_text, score=score)
            comment_obj.save()
            comment_obj.comment_sender_nickname = user_obj.nick_name
            comment_obj.comment_sender_avatar = user_obj.avatar
            comment_obj.comment_activity.add(activity_obj)
            comment_obj.save()

            result = {'code': 200}
            return JsonResponse(result, json_dumps_params={"ensure_ascii": False}, )
        else:
            fcomment_id = json_obj['comment_id']
            fcomment_obj = CommentInfo.objects.get(id=fcomment_id)
            user_obj = UserInfo.objects.get(user_name=user_name)

            comment_obj = CommentInfo(comment_text=comment_text)
            comment_obj.save()
            comment_obj.comment_sender_nickname = user_obj.nick_name
            comment_obj.comment_sender_avatar = user_obj.avatar
            fcomment_obj.comment_comment.add(fcomment_obj)
            comment_obj.save()

            result = {'code': 200}
            return JsonResponse(result, json_dumps_params={"ensure_ascii": False}, )
    except Exception as e:
        print(e)
        result = {'code': 403, 'error': '用户或活动不存在！'}
        return JsonResponse(result, json_dumps_params={"ensure_ascii": False}, )


# 点赞评论
@check_method
def like_comment(request, json_obj):
    try:
        comment_id = json_obj['comment_id']
    except Exception as e:
        print(e)
        result = {'code': 402, 'error': '未获取到数据或数据变量名错误！'}
        return JsonResponse(result, json_dumps_params={"ensure_ascii": False}, )

    try:
        comment_obj = CommentInfo.objects.get(id=comment_id)

        comment_obj.comment_like = F('comment_like') + 1
        comment_obj.save()

        result = {'code': 200}
        return JsonResponse(result, json_dumps_params={"ensure_ascii": False}, )
    except Exception as e:
        print(e)
        result = {'code': 403, 'error': '评论不存在！'}
        return JsonResponse(result, json_dumps_params={"ensure_ascii": False}, )


# 取消点赞评论
@check_method
def cancle_like_comment(request, json_obj):
    try:
        comment_id = json_obj['comment_id']
    except Exception as e:
        print(e)
        result = {'code': 402, 'error': '未获取到数据或数据变量名错误！'}
        return JsonResponse(result, json_dumps_params={"ensure_ascii": False}, )

    try:
        comment_obj = CommentInfo.objects.get(id=comment_id)

        comment_obj.comment_like = F('comment_like') - 1
        comment_obj.save()

        result = {'code': 200}
        return JsonResponse(result, json_dumps_params={"ensure_ascii": False}, )
    except Exception as e:
        print(e)
        result = {'code': 403, 'error': '评论不存在！'}
        return JsonResponse(result, json_dumps_params={"ensure_ascii": False}, )


# 删除评论
@check_method
def delete_comment(request, json_obj):
    try:
        comment_id = json_obj['comment_id']
    except Exception as e:
        print(e)
        result = {'code': 402, 'error': '未获取到数据或数据变量名错误！'}
        return JsonResponse(result, json_dumps_params={"ensure_ascii": False}, )

    try:
        comment_obj = CommentInfo.objects.get(id=comment_id)

        comment_obj.delete()

        result = {'code': 200}
        return JsonResponse(result, json_dumps_params={"ensure_ascii": False}, )
    except Exception as e:
        print(e)
        result = {'code': 403, 'error': '评论不存在！'}
        return JsonResponse(result, json_dumps_params={"ensure_ascii": False}, )
